package com.hunter.example.controller;

import com.hunter.jerrymouse.annotation.request.JsonBody;
import com.hunter.jerrymouse.annotation.request.Param;
import com.hunter.jerrymouse.annotation.request.RequestRouter;
import com.hunter.jerrymouse.annotation.response.ResponseData;
import com.hunter.jerrymouse.request.MultiPartFileRequest;
import com.hunter.jerrymouse.request.Request;
import com.hunter.jerrymouse.response.Response;
import com.hunter.jerrymouse.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;

import java.io.File;
import java.io.IOException;
import java.util.Map;

/**
 * Created by hunter
 * <p>
 * jerrymouse使用demo
 * <p>
 * 控制层接口必须注解@Controller
 * <p>
 * 就目前使用netty作为实现来说, 压测类似接口getRequestTest1, 除初次并发进来时初始化一些东西导致RQS比较少, 后续的并发请求进来时RQS基本与springboot差不多
 *
 * @RequestRouter 可以指定控制层所有接口的前缀uri和接口的http方法, 不指定http方法时可以表示接受不受方法限制
 */
@Controller
@RequestRouter(path = "test", method = {RequestRouter.Method.POST, RequestRouter.Method.GET})
public class TestController {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

    /**
     * 1. 普通的Get请求, 以参数接收
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * 优先根据@Param里面的名称注入, 其次根据参数名注入
     * 基础类型和基础类型的封装类型能进行转换赋值
     * 参数可以为null, 基础参数不传时为默认基础类型值
     * 不支持转为类对象
     */
    @RequestRouter(path = "getRequestTest1", method = RequestRouter.Method.GET)
    public String getRequestTest1(String param1, int param2, Double param3, @Param(name = "param4") String param5) {
        LOGGER.debug("param1 : {}, param2: {}, param3 : {}, param5 : {}", param1, param2, param3, param5);
        return "success";
    }

    /**
     * 2. 普通的Get请求, 以request接收参数
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * 基础类型和基础类型的封装类型能进行转换赋值
     * 参数可以为null, 基础参数不传时为默认基础类型值
     * 不支持转为类对象
     */
    @RequestRouter(path = "getRequestTest2", method = RequestRouter.Method.GET)
    public String getRequestTest2(Request request, Response response) {
        LOGGER.debug("param1 : {}, param2: {}, param3 : {}, param5 : {}",
                request.getParameter("param1"),
                request.getParameter("param2"),
                request.getParameter("param3"),
                request.getParameter("param5"));
        return "success";
    }

    /**
     * 3. 普通的Get请求, 混合接收
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * 基础类型和基础类型的封装类型能进行转换赋值
     * 参数可以为null, 基础参数不传时为默认基础类型值
     * 不支持转为类对象
     */
    @RequestRouter(path = "getRequestTest3", method = RequestRouter.Method.GET)
    public String getRequestTest3(String param1, int param2, Double param3, @Param(name = "param4") String param5,
                                  Request request, Response response) {
        LOGGER.debug("param1 : {}, param2: {}, param3 : {}, param5 : {}", param1, param2, param3, param5);

        LOGGER.debug("param1 : {}, param2: {}, param3 : {}, param5 : {}",
                request.getParameter("param1"),
                request.getParameter("param2"),
                request.getParameter("param3"), // 这里要转为double类型的话是用Double的valueOf
                request.getParameter("param5"));
        return "success";
    }

    /**
     * 4. 普通的post请求(application/x-www-form-urlencoded), 以参数接收
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * 基础类型和基础类型的封装类型能进行转换赋值
     * 参数可以为null, 基础参数不传时为默认基础类型值
     * 不支持转为类对象
     */
    @RequestRouter(path = "postRequestTest1", method = RequestRouter.Method.POST)
    public String postRequestTest1(String param1, int param2, Double param3, @Param(name = "param4") String param5) {
        LOGGER.debug("param1 : {}, param2: {}, param3 : {}, param5 : {}", param1, param2, param3, param5);
        return "success";
    }

    /**
     * 5. 普通的post请求(application/x-www-form-urlencoded), request接收 忽略 同get请求的request接收
     */

    /**
     * 6. 普通的post请求(application/x-www-form-urlencoded), 混合接收 忽略 同get请求的混合接收
     */

    /**
     * 7. post json请求(application/json), 不能以参数接收和request, 只能以类接收
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * @JsonBody 注解要讲JSON转换后的类, 这里就没有新建类了, 直接用map解决
     */
    @RequestRouter(path = "postRequestTest4", method = RequestRouter.Method.POST)
    public String postRequestTest4(@JsonBody Map<String, Object> paramMap) {
        LOGGER.debug("param : {} ", paramMap);
        return "success";
    }

    /**
     * 8. post 表单请求(multipart/form-data), 以参数接收
     *
     * @RequestRouter path指定处理的uri, method指定处理的http方法, 当与类上的处理方案不一致时优先以方法上注解的method为准
     * 文件类型需以MultiPartFileRequest接口接收, 这里的文件参数记得名称为file1或者可以用@Param指定参数名
     */
    @RequestRouter(path = "postRequestTest5", method = RequestRouter.Method.POST)
    public String postRequestTest5(MultiPartFileRequest file1, String val1) throws IOException {
        File writeFile = new File("D:\\" + file1.getFileName());
        file1.transferTo(writeFile);
        // file1.api()...
        return "success";
    }

    /**
     * 9. post 表单请求(multipart/form-data), request接收, 略 同Get请求, 参数转MultiPartFileRequest用强转即可
     */

    /**
     * 10. post 表单请求(multipart/form-data), 混合接收, 略 同Get请求, 参数转MultiPartFileRequest用强转即可
     */

    /**
     * 11. 使用response 返回数据, 使用response返回数据的方法尽量为void, 这里做个错误实例
     */
    @RequestRouter(path = "postRequestTest6")
    public String postRequestTest6(Request request, Response response) throws Exception {
        String contentType = request.getContentType();
        request.getParameter("val");
        // 使用response就代表可能不用方法返回的数据了
        response.addHeader("content-type", "text/plain");
        // response.addHeader("content-type", "application/json"); // json响应体
        // 指定正确的长度的话客户端会读取数据会有误
        response.addHeader("content-length", String.valueOf("test".getBytes().length));
        response.write("test".getBytes());
        response.flush();
        response.close(); // close 后 释放一定的资源且 return 的数据就无效了, 如果不关闭或者未指定内容长度, return的内容会继续写会给客户端, 会有影响
        return "123";
    }

    /**
     * 12. 根据返回类型返回对应的格式数据
     *
     * @ResponseData(contentType = ResponseData.ContentType.APPLICATION_JSON) 来控制对应的返回格式, 目前只有两种, 默认是TEXT/PLAIN
     */
    @RequestRouter(path = "postRequestTest7")
    @ResponseData(contentType = ResponseData.ContentType.APPLICATION_JSON)
    public Map<String, Object> postRequestTest7(@JsonBody Map<String, Object> val) {
        return val;
    }

    /**
     * 13. 文件写回demo
     */
    @RequestRouter(path = "requestTest8", method = RequestRouter.Method.GET)
    public void requestTest8(Request request, Response response) throws Exception {
        String requestFilePath = (String) request.getParameter("filePath");
        File file = new File(requestFilePath);
        FileUtils.write(file, file.getName(), response, request.keepAlive());
    }
}
